function edit_control(cmd, arg1)
% make new figure to open for editing the selected entry of CTL
% returns the modified entry in the case that Update is selected,
% returns the unmofified entry in the case that Dismiss is selected

persistent MODIFIED;
global DFILE

global CONTROL

switch(cmd)

    case 'edit'
        makeeditor;
        MODIFIED = 0;

    case 'update'
        toggle_display('List');
        setlist (getmainselection);
        close;
        return;

    case 'updateandsave'
        datac('savematctl');
        toggle_display('List');
        setlist (getmainselection);
        close;
        return;

    case 'dismiss'
        if(~MODIFIED)
            close
            return;
        end
        button = questdlg('Are you sure you want to discard any changes?',...
            'Continue Operation','Yes','No','Help','No');
        if strcmp(button,'Yes')
            CONTROL = geteditdata; % get the saved, unmodified version of the database
            close
            return
        end

    case 'EditDispatch' % do the edit operation...
        mod = EditDispatch;
        if(mod)
            MODIFIED = 1;
        end

    case 'BridgeBalance'
        bridge_adjust('init'); % just start the new bridge window
        datac('refresh');

    case 'NewBridge' % calls us back to set the new value
        new_bridge=arg1; % get the value
        % new_bridge
        disp(sprintf('New bridge: %7.1f', new_bridge))
        if(~isempty(new_bridge))
            MODIFIED=1;
            sflag = getmainselection; % get the pointer to the element of the set
            if(sflag==0 || length(sflag) > 1)
                QueMessage('Edit: couldn''t get valid selection?')
                return % make sure its valid...
            end
            h2 = findobj('Tag', 'EditCTL');
            sel = get(h2, 'Value'); % find the data element in the list
            CONTROL(sflag).access=CONTROL(sflag).access+new_bridge; % update the access field. Note access is change...
            CONTROL(sflag).access
            lastchange = datestr(now, 0);
            CONTROL(sflag).lastupdate = lastchange; % keep track of update information
            updateeditwindow(sflag, sel);
        end

    case 'OOPatch' % set OO patch defaults...
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h2 = findobj('Tag', 'EditCTL');
        sel = get(h2, 'Value'); % find the data element in the list
        CONTROL(sflag).vgain=1;
        CONTROL(sflag).igain=10;
        CONTROL(sflag).jpot=-12; % kgluc
        CONTROL(sflag).mode='VC';
        CONTROL(sflag).durho=5;
        CONTROL(sflag).durs1=100; % defaults for qinactp2/p3
        CONTROL(sflag).durs2=300;
        CONTROL(sflag).durs3=100;
        CONTROL(sflag).leakwin=3;
        updateeditwindow(sflag, sel);
        MODIFIED = 1;

    case 'CAPatch' % set Cell-attached patch defaults...
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h2 = findobj('Tag', 'EditCTL');
        sel = get(h2, 'Value'); % find the data element in the list
        CONTROL(sflag).vgain=-1;
        CONTROL(sflag).igain=20;
        CONTROL(sflag).jpot=-60; % kgluc
        CONTROL(sflag).mode='VC';
        CONTROL(sflag).durho=10;
        CONTROL(sflag).durs1=300; % defaults for qinactp2/p3
        CONTROL(sflag).durs2=0;
        CONTROL(sflag).durs3=0;
        CONTROL(sflag).leakwin=0;
        CONTROL(sflag).transwin=0;
        updateeditwindow(sflag, sel);
        MODIFIED = 1;

    case 'CClamp' % set Current-clamp defaults (like cciv)...
        do_cclamp;
        MODIFIED = 1;

    case 'HWF'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h2 = findobj('Tag', 'EditCTL');
        sel = get(h2, 'Value'); % find the data element in the list
        CONTROL(sflag).vgain=2;
        CONTROL(sflag).igain=0.5;
        CONTROL(sflag).jpot=0; % KCl sharp
        CONTROL(sflag).mode='CC';
        CONTROL(sflag).thresh=-20;
        switch(unblank(CONTROL(sflag).protocol))
            case {'iv', 'cciv'}
                CONTROL(sflag).durho=10;
                CONTROL(sflag).durs1=100;
                CONTROL(sflag).durs2=0;
                CONTROL(sflag).durs3=0;
            otherwise
        end;
        updateeditwindow(sflag, sel);
        MODIFIED = 1;

    case 'FP'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h2 = findobj('Tag', 'EditCTL');
        sel = get(h2, 'Value'); % find the data element in the list
        CONTROL(sflag).vgain=200;
        CONTROL(sflag).igain=0.5;
        CONTROL(sflag).jpot=0; % extracellular
        CONTROL(sflag).mode='FP';
        CONTROL(sflag).thresh=0;
        CONTROL(sflag).protocol = 'IO';
        CONTROL(sflag).stim_time = '[5,55]';
        CONTROL(sflag).psp_time = '[6.1,8.3,8.3,10.9,9.2,20.5]';
        CONTROL(sflag).psp_reclist = ' ';
        CONTROL(sflag).sign_list = '[-1,-1,1]';
        CONTROL(sflag).reclist = '1;21';
        updateeditwindow(sflag, sel);
        MODIFIED = 1;

    case 'VClamp' % set Voltage-clamp defaults (like vciv)...
        do_vclamp;
        MODIFIED = 1;

    case 'upcomment'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_comment');
        if(~isempty(h))
            CONTROL(sflag).Commentary=get(h, 'string');
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;
    case 'upec'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_ec');
        if(~isempty(h))
            CONTROL(sflag).E_C=get(h, 'string');
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;

    case 'upg1'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_g1');
        if(~isempty(h))
            CONTROL(sflag).G1=str2double(get(h, 'string'));
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;

    case 'upg2'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_g2');
        if(~isempty(h))
            CONTROL(sflag).G2=str2double(get(h, 'string'));
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;

    case 'uppnd'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_pnd');
        if(~isempty(h))
            CONTROL(sflag).pnd=str2ndouble(get(h, 'string'));
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;

    case 'updiv'
        sflag=getmainselection;
        if(sflag==0 || length(sflag) > 1)
            QueMessage('Edit: Couldn''t get valid selection?');
            return;
        end;
        h=findobj('tag', 'edit_div');
        if(~isempty(h))
            CONTROL(sflag).div=str2double(get(h, 'string'));
        end;
        updateeditwindow(sflag, 1);
        MODIFIED = 1;


    case 'auto' % automatic determination as best we can - no interactive capability at all.....
        switch(DFILE.dmode)
            case ('CC')
                do_cclamp;
                MODIFIED = 1;
            case ('VC')
                do_vclamp;
                MODIFIED = 1;
            otherwise
        end;
        return;

    otherwise
end

return;


% -------------------------------------------------
% make the editor list - just read the names from the
% control stucture stored in userdata of the main window
% and build a list based on that
% the list callback routes to a routine that handles the
% display window when we double-click
%
% 12/8/98 P. Manis

function makeeditor()
global CONTROL

% get the data and put it in our window
sel = getmainselection;
if(sel == 0)
    QueMessage('edit_control: No selection', 1);
    return; % never open the window - just return
end;

if(length(sel) > 1)
    QueMessage('edit_control: Please select only one entry', 1);
    return;
end;

scrsz = get(0,'ScreenSize'); % determine the position of the figure in the system window
size=0.5;
scrb = scrsz(4)*((1-size)/2);
scrl = scrsz(3)*((1-size)/4);
scrwd = 500; % scrsz(3)*size;
scrht = 500; % scrsz(4)*size*1.25;

h0 = findobj('Tag', 'Edit'); % check for pre-existing window
if(isempty(h0)) % if none, make one
    h0 = figure('Tag', 'Edit');
    set(h0, 'Color', 'black', ...
        'Colormap',[1,1,1], ...
        'Position', [scrl, scrb, scrwd, scrht], ...
        'Name', 'Edit', ...
        'NumberTitle', 'off');

end
figure(h0); % otherwise, select the existing one and overwrite it
clf; % always clear the window...

set(h0, 'Units', 'characters');
figsz=get(h0, 'Position');

b_ht = 1.7;
pad_check = 7; pad_edit = 5; pad_list = 5; pad_pop = 7;
pad_push = 4; pad_radio = 7; pad_static = 4;
but_vpad = 0.125;
but_hpad = 1.5;

but_vspc = b_ht + but_vpad; % space to allocate for each button or field

buttonlist = [];
buttonlist = add_button(buttonlist, 'Update', 'edit_control update', 'Update Record Information', 'Update', 'on');
buttonlist = add_button(buttonlist, 'Update & Save', 'edit_control updateandsave', 'Update and Save Record Information', 'Update and save', 'on');
buttonlist = add_button(buttonlist, 'Adjust Bridge', 'edit_control BridgeBalance', 'Change bridge balance', 'Adjust Bridge', 'on');
buttonlist = add_button(buttonlist, 'OO-patch def', 'edit_control OOPatch', 'Set OO patch Defaults', 'Set OO Patch defaults', 'on');
buttonlist = add_button(buttonlist, 'CA-patch def', 'edit_control CAPatch', 'Set CA patch Defaults', 'Set CA Patch defaults', 'on');
buttonlist = add_button(buttonlist, 'CClamp def', 'edit_control CClamp', 'Set C-Clamp Defaults', 'Set C-Clamp defaults', 'on');
buttonlist = add_button(buttonlist, 'VClamp def', 'edit_control VClamp', 'Set V-Clamp Defaults', 'Set C-Clamp defaults', 'on');
buttonlist = add_button(buttonlist, 'HWF CC def', 'edit_control HWF', 'Set HWF C-Clamp Defaults', 'Set HWF C-Clamp defaults', 'on');
buttonlist = add_button(buttonlist, 'FP def', 'edit_control FP', 'Set FP C-Clamp Defaults', 'Set FP C-Clamp defaults', 'on');

buttonlist = add_button(buttonlist, 'Dismiss', 'edit_control dismiss', 'Dismiss Record Changes', 'Dismiss', 'on', 1);

maxtitle = 0;
for i=1:length(buttonlist)
    l = length(buttonlist(i).title);
    if(l > maxtitle)
        maxtitle = l;
    end
end
but_width = maxtitle+2*but_hpad;
button_x = figsz(3) - but_width-but_hpad;  % place the buttons to the right side of the display
button_y = figsz(4)*0.85-1;

localctl = CONTROL;
seteditdata(localctl); % store locally

% List box to access each element of the control table
% the listbox exists inside the main frame and is swapped with the graphics as necessary.
%
uicontrol('Parent',h0, ...
    'Units','characters', ...
    'ListboxTop',1, ...
    'FontUnits', 'points', ...
    'FontName', 'Lucida Console', ...
    'FontSize', 8, ...
    'BackgroundColor',[0 0 0], ...
    'ForegroundColor', [1.0 0.8 0.1]', ...
    'Position',[1 1 60 30], ...
    'String','<empty>', ...
    'Style', 'Listbox', ...
    'Callback', 'edit_control EditDispatch', ...
    'Tag','EditCTL');

updateeditwindow(sel, 1); % set to top

cmd_vspc = but_vspc + 2*but_vpad; % extra padding
for i=1:length(buttonlist)
    b_y = button_y-i*cmd_vspc;
    if(~isempty(buttonlist(i).pos))
        b_y = 1;
    end
    uicontrol('Parent', h0, ...
        'Units', 'characters', ...
        'FontUnits', 'points', ...
        'FontName', 'Arial', ...
        'FontSize', 9, ...
        'ForegroundColor', 'blue', ...
        'Position', [button_x b_y but_width+0.5 b_ht], ...
        'String', buttonlist(i).title, ...
        'Callback', buttonlist(i).callback, ...
        'Enable', buttonlist(i).enable, ...
        'Tag', buttonlist(i).tag);
end


% place special group edits here
% Comment
% Experimental Condition
% Group 1
% Group 2
% PND

h = textentry('edit_comment', 'Comment', CONTROL(sel).Commentary, 64, 1, 37);
set(h, 'Callback', 'edit_control(''upcomment'')');
set(h, 'horizontalalignment', 'left');

h = textentry('edit_ec', 'Expt. Condition', CONTROL(sel).E_C, 5, 1,35);
set(h, 'Callback', 'edit_control(''upec'')');

h = textentry('edit_g1', 'G1 ', CONTROL(sel).G1, 5, 30,35);
set(h, 'callback', 'edit_control(''upg1'')');

h = textentry('edit_g2', 'G2 ', CONTROL(sel).G2, 5, 45,35);
set(h, 'callback', 'edit_control(''upg2'')');

h = textentry('edit_pnd', 'PND', CONTROL(sel).pnd, 5, 30,33);
set(h, 'callback', 'edit_control(''uppnd'')');

h = textentry('edit_div', 'DIV', CONTROL(sel).div, 5, 45,33);
set(h, 'callback', 'edit_control(''updiv'')');


return;


% update the list in the edit window for the control structure
% note that we consider lower level structures priveleged - they can be viewed
% but the cannot be edited. (they are normally used to store
% results from data analysis)
% 12/8/98 P. Manis

function updateeditwindow(SEL, pos)

global CONTROL

if(length(SEL) > 1)
    QueMessage('Edit: too many items selected', 1);
    return;
end;
names=fieldnames(CONTROL);

listinfo='';
for i=1:size(names, 1)
    thisname = char(names(i));
    arg = strcat('CONTROL(SEL).', thisname);
    if(isstruct(eval(char(arg))))
        listthis = sprintf('%s : STRUCT', thisname);
    end
    if(isnumeric(eval(char(arg))))
        x=eval(char(arg));
        if(any(size(x)>1))
            listthis=strcat(sprintf('%s  =  ',thisname), num2str(x));
        else
            listthis = sprintf('%s = %g', thisname, eval(char(arg)));
        end;
    end
    if(ischar(eval(char(arg))))
        listthis = sprintf('%s = ''%s''', thisname, eval(char(arg)));
    end
    if(isempty(eval(char(arg))))
        listthis = sprintf('%s = <empty>', thisname);
    end

    listinfo = strvcat(listinfo, listthis);
end

h1=findobj('Tag', 'EditCTL');
if(ishandle(h1))
    if(strmatch(computer, 'MAC')) % font stuff...
        set(h1,'FontName', 'FixedWidth');
        set(h1, 'FontSize', 11);
        set(h1, 'FontWeight', 'bold');
        set(h1, 'Foregroundcolor', 'yellow');
    end;
    set(h1, 'String', listinfo);
end
set(h1, 'Value', pos); % set to that position in the scroll
return;


function [modified] = EditDispatch()
% EditDispatch brings up a window allowing the data field to be edited
% or viewed if it is a structure
%
global CONTROL

modified = 0;
htag = findobj('Tag', 'Edit'); % get the window
s=get(htag, 'SelectionType'); % read the click FROM THE MAIN WINDOW
h2 = findobj('Tag', 'EditCTL');
set(htag, 'Units', 'Pixels');
Pos = get(htag, 'Position');
Pos(1) = Pos(1) -10;
Pos(2) = Pos(2) + Pos(4)-140;

set(htag, 'Units', 'Characters');
switch (s)
    case 'normal' % single click
        sel = get(h2, 'Value'); % find the data element in the list
        list=cellstr(get(h2,'String'));
        sflag = getmainselection; % get the pointer to the element of the set
        if(sflag==0 || length(sflag) > 1)
            return % make sure its valid...
        end;
        names = fieldnames(CONTROL(sflag)); % read the fields
        x=list(sel);
        x=deblank(strtok(char(x), ':='));
        thisname = char(names(strmatch(x, char(names), 'exact')));
        % return the correct pointer.
        ptr = strcat('CONTROL(sflag).', char(thisname)); % generate the field to access as a string
        prompt  = {sprintf('Enter %s', thisname)};
        lines= 1;
        if (isempty(eval(char(ptr)))) % there was no type!
            title   = sprintf('Modify <empty> Field %s', thisname) ;
            def = {' '};
            arg  = my_inputdlg(prompt,title,lines,def, 'off', Pos(1:2));
            if(~isempty(arg) && ~strcmp(char(arg), char(def)))
                arg=strjust(char(arg), 'left');
                eval([char(ptr),'=char(arg);']);
                modified = 1;
            end
        elseif (isnumeric(eval(char(ptr))))
            title   = sprintf('Modify Numeric Field %s', thisname) ;
            %      def = { num2str(eval(char(ptr))) };
            def = {sprintf('%g ',eval(char(ptr))) };
            answer  = my_inputdlg(prompt,title,lines,def, 'off', Pos(1:2));
            if(~isempty(answer) && ~strcmp(char(answer), def))
                if(any(char(answer) == '[') && any(char(answer) == ']')) % possible matlab array argument
                    arg = strjust(char(answer), 'left');
                    eval([char(ptr),'=char(answer);']);
                else
                    arg = str2num(char(answer));
                    eval([char(ptr),'=arg;']);
                end;
                modified = 1;
            end
        elseif (ischar(eval(char(ptr))))
            title   = sprintf('Modify string Field %s', thisname) ;
            def = { eval(char(ptr)) };
            arg  = my_inputdlg(prompt,title,lines,def, 'off', Pos(1:2));
            if(~isempty(arg) && ~strcmp(char(arg), char(def)))
                arg = strjust(char(arg), 'left');
                eval([char(ptr),'=char(arg);']);
                modified = 1;
            end
        elseif (isstruct(eval(char(ptr))))
            %        disp(sprintf('%s is structure', thisname))
            title = char(eval('CONTROL(sflag).filename'));
            if(strcmp(thisname, 'NOTEFILE')) % handle special
                info = notelist(CONTROL(sflag).NOTEFILE);
            else
                snames = fieldnames(eval(char(ptr)));
                u=length(snames);
                info = sprintf('\nResults Structure: %s (IMMUTABLE)', upper(thisname));
                for k=1:u
                    stru=sprintf('%s.%s', char(ptr), char(snames(k)));
                    eval(['len = length([' stru ']);']);
                    if(len > 1)
                        info=strvcat(info, sprintf('%-15s =  Array[%d]', char(snames(k)), len)); % don't print arrays - just tell us the length
                    else
                        ll = sprintf('%-15s = %15g', char(snames(k)), eval(char(sprintf('%s.%s', char(ptr), char(snames(k))))));
                        info = strvcat(info, ll);
                    end
                end
            end;
            msgbox(info, title, 'replace');
        end
    otherwise
end;
if(modified)
    lastchange = datestr(now, 0);
    CONTROL(sflag).lastupdate = lastchange; % keep track of update information
    %   setuserdata(control); % force update of original data in main window
    updateeditwindow(sflag, sel);
    modified = 0;
end
return;



function [ctl] = geteditdata()
%-----------------------------------------------------------------------
% get the data as userdata in EditCTL (the main window) so we can access it
% as the control dataset - used only if we dismiss...
ctl = [];
htag = findobj('Tag', 'Edit');
if(htag == 0)
    return;
end
ctl = get(htag, 'UserData');
return

function seteditdata(ctl)
%-----------------------------------------------------------------------
% set the data as userdata in EditCTL (the main window) so we can access it
% in the listcontrol box.....
% used to store the original control worksheet before modifications..
htag = findobj('Tag', 'Edit');
if(htag == 0)
    return;
end
set(htag, 'UserData', ctl);
return


function [list] = notelist(proto)
% based on pastenote...
% paste a note into the window selected by notefile as text
% assumes proto is a structure as in protocol as shown here:
% proto -> protocol is an array structure itself, as follows:
%		protocol(n).proto	the name of the protocol
%		protocol(n).seq		the sequence that was to be run
%		protocol(n).frec		the first record in the protocol
%		protocol(n).lrec		the last record in the protocol
%		protocol(n).ztime		the starting time of the protocol in ztime ( set to 0 here; can be set later when data file is read)
%		protocol(n).etime		the starting time of the protocol in "real time" (read from notefile)
%		protocol(n).valve		the valve in use at the time.
%		protocol(n).notes		the concatenation of note entries since the last protocol


np=size(proto);
list='';


valve=1;
for i=1:np(2)
    if(~isempty(proto(i).notes))
        al=strcat('* ', proto(i).notes);
        list=strvcat(list, al);
    end;
    % check the valve situation
    if(proto(i).valve ~= valve) % display it if it has changed.
        valve=proto(i).valve;
        list = strvcat(list, sprintf('@ VALVE: %3d ', valve));
    end;

    % now put up the protocol;
    if(proto(i).lrec >= proto(i).frec)
        cmd=sprintf('> %4d %4d %8s %14s ', proto(i).frec, proto(i).lrec, proto(i).proto, proto(i).seq);
    else
        cmd='';
    end
    list = strvcat(list, cmd);

end
return;

function do_cclamp()

set_ccpar;
sflag=getmainselection;
if(sflag==0 || length(sflag) > 1)
    QueMessage('Edit: Couldn''t get valid selection?');
    return;
end;
h2 = findobj('Tag', 'EditCTL');
if(~isempty(h2) && ishandle(h2))
    sel = get(h2, 'Value'); % find the data element in the list

    updateeditwindow(sflag, sel);
end;
return;

function do_vclamp()
set_vcpar;
sflag=getmainselection;
if(sflag==0 || length(sflag) > 1)
    QueMessage('Edit: Couldn''t get valid selection?');
    return;
end;
h2 = findobj('Tag', 'EditCTL');
if(~isempty(h2) && ishandle(h2))
    sel = get(h2, 'Value'); % find the data element in the list

    updateeditwindow(sflag, sel);
end;
return;

